﻿using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;

namespace ReadPLC
{
    internal class Program
    {
        static int num1 = 0;
        static int num2 = 0;
        static bool isMainEnd = false;
        static ConcurrentDictionary<int, object> dict = new ConcurrentDictionary<int, object>();
        static Stopwatch stopwatch = Stopwatch.StartNew();

        static void Main(string[] args)
        {
            ThreadPool.SetMinThreads(100, 100);

            CalcSpeed();

            BatchReadPLC2();
            BatchReadPLC1();

            isMainEnd = true;
            Console.WriteLine("执行到Main函数结尾");
            Console.ReadLine();
        }

        static void BatchReadPLC1()
        {
            Task.Factory.StartNew(() =>
            {
                while (true)
                {
                    // 批量读取，第1个参数是一个集合，第2个参数是并行度
                    Parallel.ForEach(Enumerable.Range(0, 500), new ParallelOptions() { MaxDegreeOfParallelism = 500 }, (i, c) =>
                    {
                        ReadPLC(i);
                    });

                    Thread.Sleep(200); // 每200毫秒批量读取一次
                }
            }, TaskCreationOptions.LongRunning);
        }

        static void ReadPLC(int plcIndex)
        {
            dict.TryAdd(plcIndex, null);

            // todo: 读取PLC
            Thread.Sleep(50); // 模拟同步方式读取PCL耗时
            // Console.WriteLine($"读取PLC完成，plcIndex={plcIndex}");
            Interlocked.Increment(ref num1);
        }

        static void BatchReadPLC2()
        {
            for (int i = 0; i < 500; i++)
            {
                Thread thread = new Thread(() =>
                {
                    while (true)
                    {
                        // todo: 读取PLC
                        Thread.Sleep(50); // 模拟同步方式读取PCL耗时
                        //Console.WriteLine($"读取PLC完成，plcIndex={plcIndex}");
                        Interlocked.Increment(ref num2);

                        Thread.Sleep(200);
                    }
                });
                thread.Start();
            }
        }

        static void CalcSpeed()
        {
            _ = Task.Factory.StartNew(() =>
            {
                Stopwatch sw = Stopwatch.StartNew();
                while (true)
                {
                    Thread.Sleep(2000);
                    double speed1 = num1 / sw.Elapsed.TotalSeconds;
                    double speed2 = num2 / sw.Elapsed.TotalSeconds;
                    Console.WriteLine($"已运行 {stopwatch.Elapsed.TotalSeconds:0.000} 秒");
                    Console.WriteLine($"  异步方式 速度={speed1:#### ####.0} 次/秒");
                    Console.WriteLine($"多线程方式 速度={speed2:#### ####.0} 次/秒");
                    Console.WriteLine(isMainEnd ? "已执行到Main函数结尾" : "尚未执行到Main函数结尾");
                    Console.WriteLine($"有{500 - dict.Count}个PLC一次都没有读取");
                    Console.WriteLine();
                }
            }, TaskCreationOptions.LongRunning);
        }
    }
}
